package com.atguigu.crowd.handler;

import com.atguigu.crowd.api.MySQLRemoteService;
import com.atguigu.crowd.api.RedisRemoteService;
import com.atguigu.crowd.config.ShortMessageProperties;
import com.atguigu.crowd.constant.CrowdConstant;
import com.atguigu.crowd.entity.po.MemberPO;
import com.atguigu.crowd.entity.vo.MemberLoginVO;
import com.atguigu.crowd.entity.vo.MemberVO;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import org.apache.http.protocol.HTTP;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import javax.sound.midi.Soundbank;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Controller
public class MemberHandler {

    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private RedisRemoteService redisRemoteService;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;


    // 退出登录
    @RequestMapping("/auth/do/member/logout.html")
    public String doLogout(HttpSession session) {

        // 清除session域数据
        session.invalidate();

        // 重定向到首页
        return "redirect:http://localhost/";
    }
    

    @RequestMapping("/auth/do/member/login.html")
    public String login(
            @RequestParam("loginAcct") String loginAcct,
            @RequestParam("loginPswd") String loginPswd,
            ModelMap modelMap,
            HttpSession httpSession) {

        //1、调用远程接口根据登录账号查询MemberPO对象
        ResultEntity<MemberPO> memberPOByLoginAcctRemote = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginAcct);

        // 判断-查询操作是否成功
        if (ResultEntity.FAILED.equals(memberPOByLoginAcctRemote.getResult())) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, memberPOByLoginAcctRemote.getMessage());
            return "member-login";
        }

        MemberPO memberPO = memberPOByLoginAcctRemote.getData();
        // 判断得到的MemberPO是否为空
        if (memberPO == null) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        //2、比较密码
        String userpswdDataBase = memberPO.getUserPswd();
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(loginPswd, userpswdDataBase);
        if (!matches) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        // 3、创建MemberLoginVO对象存到session域中
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUserName(), memberPO.getEmail());

        // 将LoginMemberVO对象存入session域(因为session会放入redis，因此LoginMemberVO必须实现序列化)
        httpSession.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER, memberLoginVO);

        // 重定向到登陆成功后的主页面
        return "redirect:http://localhost/auth/to/member/center/page.html";
    }


    @RequestMapping("/auth/member/do/register.html")
    public String register(MemberVO memberVO, ModelMap modelMap) {

        //1、获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum();

        //2、拼接Redis中存储验证码的Key
        String key = "redis_code_prefix_" + phoneNum;

        //3、从Redis中读取key对应的value
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);

        // 4、检查查询操作是否有效
        String result = resultEntity.getResult();
        if (ResultEntity.FAILED.equals(result)) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getMessage());
            return "member-reg";
        }

        //5、如果从Redis能够查询到value则比较表单的验证码和Redis的验证码
        String value = resultEntity.getData();
        if (value == null) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-reg";
        }

        String formCode = memberVO.getCode();
        if (!Objects.equals(formCode, value)) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_INVALID);
            return "member-reg";
        }

        //6、如果验证码一致，则从Redis删除
        redisRemoteService.removeRedisKeyRemote(key);

        //7、执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String userPswd = memberVO.getUserPswd();
        String encode = passwordEncoder.encode(userPswd);
        memberVO.setUserPswd(encode);

        //8、执行保存
        //8.1、创建空的MemberPO对象
        MemberPO memberPO = new MemberPO();
        //8.2、复制属性
        BeanUtils.copyProperties(memberVO, memberPO);
        //8.3、调用远程方法
        ResultEntity<String> saveMember = mySQLRemoteService.saveMember(memberPO);

        if (ResultEntity.FAILED.equals(saveMember.getResult())) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, saveMember.getMessage());
            return "member-reg";
        }
        //使用重定向避免刷新浏览器，导致重新执行注册流程
        return "redirect:http://localhost/auth/to/member/login/page.html";
    }

    @ResponseBody
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum) {
        //1、发送验证码到phoneNum手机
        ResultEntity<String> sendMessageResultEntity = CrowdUtil.sendCodeByShortMessage(
                phoneNum,
                shortMessageProperties.getAccesskey(),
                shortMessageProperties.getSecret(),
                shortMessageProperties.getSignName(),
                shortMessageProperties.getTemplateCode());

        //2、判断短信发送结果
        if (!ResultEntity.SUCCESS.equals(sendMessageResultEntity.getResult())) {
            // 发送验证码失败，返回发送验证码的ResultEntity
            return sendMessageResultEntity;
        }

        //3、如果发送成功，则将验证码存入redis
        //3.1、获取随机生成的验证码
        String code = sendMessageResultEntity.getData();
        //3.2、拼接redis的key
        String key = "redis_code_prefix_" + phoneNum;
        //3.3、调用远程接口存入redis
        ResultEntity<String> saveCodeResultEntity = redisRemoteService.setRedisKeyValueWithTimeOutRemote(key, code, 15, TimeUnit.MINUTES);

        if (!ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())) {
            // 存入失败，返回redis返回的ResultEntity
            return saveCodeResultEntity;
        }

        return ResultEntity.successWithoutData();

    }

}
